from ctypes import CDLL

class EnigmaMachine(object):

    initialized = False
    dll = CDLL('.\enigma.dll')

    @classmethod
    def wrapper_initialize(cls, count, rotors='I II III', ring_settings='0 0 0', reflector='B'):
        if cls.initialized:
            raise RuntimeError('EnigmaMachine is already initialized')

        cls.dll.py_wrapper_initialize(count, rotors, ring_settings, reflector, len(rotors), len(ring_settings), len(reflector))
        cls.initialized = True

    def __init__(self):
        if not self.initialized:
            raise RuntimeError('EnigmaMachine should be initialized before creating a machine')
        try:
            self.id = self.dll.py_wrapper_create_enigma_machine()
        except Exception as e:
            print e
            raise RuntimeError('Exception calling C interface')

        if self.id == -1:
            raise RuntimeError('Failed creating an enigma machine')

        self.destroyed = False

    def set_display(self, display):
        if self.destroyed:
            raise RuntimeError('Enigma machine already destroyed')
        try:
            i = self.dll.py_wrapper_set_display(self.id, display)
        except:
            raise RuntimeError('Exception calling C interface')
        if not i:
            raise RuntimeError('Failed setting display')

    def process_text(self, text):
        if self.destroyed:
            raise RuntimeError('Enigma machine already destroyed')
        _text = text.upper()
        try:
            i = self.dll.py_wrapper_process_text(self.id, _text, len(_text))
        except:
            raise RuntimeError('Exception calling C interface')
        if not i:
            raise RuntimeError('Failed processing text')

        return _text

    def destroy(self):
        if self.destroyed:
            raise RuntimeError('Enigma machine already destroyed')
        try:
            i = self.dll.py_wrapper_destroy(self.id)
        except:
            raise RuntimeError('Exception calling C interface when releasing memory')
        if not i:
            raise RuntimeError('Failed releasing memory')

        self.destroyed = True

def add_uppercase(text):
    _text = text.lower()
    try:
        i = EnigmaMachine.dll.py_do_upper(_text, len(_text))
    except:
        raise RuntimeError('Exception calling C interface')
    if not i:
        raise RuntimeError('Failed processing text')

    return _text
